2015-08-19

創用 CC 授權條款

Function / Program in R

Program:

程式:

資料 or 資料結構





Data Structure:

剛剛上一位講者: Ning 已經教過了,忘了要記得複習喔!

小小複習一下:


numeric1 = c(2, 3, 5) 

string1 = c("aa", "bb", "cc") 

boolean1 = c(TRUE, FALSE, TRUE) 

data1 = data.frame(numeric1, string1, boolean1)

##   number1 string1 boolean1
## 1       2      aa     TRUE
## 2       3      bb    FALSE
## 3       5      cc     TRUE

什麼叫程式





目的是用來處理「特定資料」,

根據演算法將多個函式或是指令組成的集合




簡單說,寫一個程式,其實和 寫一段文章,或是一篇小說差不多,

Function 或 演算法





數學上叫函數,

程式語言中叫函式

為什麼要用function:



1. 可以把相同「目的」指令和資料整理在一起


2. 可重複使用


3. 可方便程式的閱讀


by 民明書房 Noah

function的用法:

可用R來查詢定義:




?function(){}


用法:




函式名稱 = function(引數) {

  程式的內容........

}

愛護生命,建議千萬不要用中文當作變數及函式名字,現在出現中文只是用來說明

範例1:Hello World

第一個R的程式:





請在R 中顯示:Hello World, R


Hello World







  print("Hello World, R")

Hello World





helloworld <- function(){

  print("Hello World, R")

}

範例:可以帶入變數


helloworld <- function(my_name){

  print(paste("Hello World,", my_name))
}

執行:

helloworld("DSC2015")

## [1] "Hello World, DSC2015"

helloworld:函式名稱,
my_name:此函式所帶入的參數,

範例2:

顯示現在的時間:


print("現在的時間和日期是:")

print(date())


## [1] "現在的時間和日期是:"
## [1] "Wed Aug 19 14:43:43 2015"

分別顯示現在的日期和時間:


    print("現在的日期是:")
    print(paste(substr(date(),21,24), substr(date(),5,10), substr(date(),1,3)))

## [1] "現在的日期是:"
## [1] "2015 Aug 19 Wed"

    print("現在的時間是:")
    print(substr(date(),12,19))

## [1] "現在的時間是:"
## [1] "14:43:43"

用一個名字將上面的程式包起來


now1 <- function(){

    print("現在的日期是:")
    print(paste(substr(date(),21,24), substr(date(),5,10), substr(date(),1,3)))
    print("現在的時間是:")
    print(substr(date(),12,19))
}

使用function

在console下輸入指定的名稱和括號:

now_time()

## [1] "現在的日期是:"
## [1] "2015 Aug 19 Wed"
## [1] "現在的時間是:"
## [1] "14:43:43"

程式儲存及執行

用R studio 或用文字編輯器存成.R檔

執行R程式:

用source指令:

source("iris.r")

Q & A

課程預告:

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

R 專題實習 , by wush

END…..?

現在已經把R的基本的function和data都介紹完了,

相信有不少人應該可以自豪的說:學了R以後,

那….我來幹嘛?

泛舟嗎?

讓我們來寫一些 R 的程式吧!~

對了,

如果課程中有任何問題都可以問助教
R社群最神奇的地方就是:







助教什麼都會!

貼心小提醒1:

遇到不會的指令可以用下面方法查詢:

『?』+『指令』

『example』『(』+『指令』+『)』

ex:

?list
example(factor)

貼心小提醒2:







善用「tab」按鍵

Syllabus

Syllabus1:


Function


編輯撰寫屬於你的第一個R程式

Syllabus2:

Flow Control


判斷條件控制 
- if / else

迴圈控制 
- for(),
- while(),

Syllabus3:

Debug and Error/Exception Handling


- 除錯(找蟲)
- debug() / undebug()

程式錯誤及例外處理
try() / tryCatch()

Flow Control:程式流程控制:

if / else:

==> 如果xxxx,那就xxxx,否則xxxx


Syntex:

    if (condition_1){
        #Do something here....
    } else if (conditon_2){
        #Do something here
    } else {
        #Do something here
    }


Note: **else if** and **else** are optional.

邏輯:




[TRUE] or [T]




[FALSE] or [F]

if /else 邏輯判斷符號

"==":等於

"1" == "1"


[1] TRUE


"1" == "2"


[1] FALSE

if / else 邏輯判斷符號

"<=":小於等於

"1" <= "1"


[1] TRUE


"1" <= "2"


[1] FALSE

if / else 邏輯判斷符號

"<":小於

"1" < "2"


[1] TRUE


"1" < "1"


[1] FALSE

if / else 邏輯判斷符號

">=":大於等於

"1" >= "1"


[1] TRUE


"1" >= "2"


[1] FALSE

if / else 邏輯判斷符號

">":大於

"2" > "1"


[1] TRUE


"1" > "1"


[1] FALSE

if / else 邏輯判斷符號

"!=":不等於

"2" != "1"


[1] TRUE


"1" != "1"


[1] FALSE

if / else 邏輯判斷符號

"&":邏輯中的「且」 或「and」

"1" == "1" && "2" == "2"


[1] TRUE


("1" == "2")  &&  ("2" == "2")


[1] FALSE

if / else 邏輯判斷符號

"|":邏輯中的「或」 或「or」

("1" == "1")  ||  ("2" == "2")


[1] TRUE


("1" == "2")  ||  ("2" == "2")


[1] TRUE


("1" == "2")  ||  ("2" == "3")


[1] FALSE

那會了if和邏輯符號,可以怎麼用?

範例:小明看電影

小明現在6歲,電影小小兵是保護級,

那小明可不可以看電影小小兵?

用一般的方法說:




如果小明滿7歲的話,那就可以看小小兵,如果沒有的話,那就不能看。

條件判斷1

1. 小明6歲


小明 = 6

2. 保護級條件:

未滿7歲之兒童不宜觀賞,
7歲以上未滿12歲之少年需父母或師長輔導觀賞。

不能看
保護級年紀規定 = 大於等於7歲,而且也要小於12歲
保護級最低年紀規定 = 大於等於7歲
保護級需要父母陪同的最高年紀規定 = 小於12歲
保護級不需要父母陪同的年紀規定 = 12歲以上

如果小明>7歲的話:


if (小明 >= 保護級最低年紀規定){
    print(可以看)
}"

如果小明<7歲的話:


if (小明 < 保護級最低年紀規定){
print(就是不讓你看)
}

那就寫成程式吧:

註:愛護生命,變數請一定用英文


小明 = 7;
保護級最低年紀 = 7;
if(小明 > 保護級最低年紀) {
  print("YES, 小明 可以看~~")
} 

[1] 小明可以看


if(小明 < 保護級最低年紀) {
  print("NO, T_T 小明 不能看")
} 

[1] __________

我知道上面的例子有點簡單,

範例:閏年

請判斷輸入的年份是不是閏年?


目前使用的格里曆閏年規則如下:


西元年份除以400可整除=閏年。

西元年份除以4可整除但除以100不可整除=閏年。

西元年份除以4不可整除=平年。

西元年份除以100可整除但除以400不可整除=平年


https://zh.wikipedia.org/zh-tw/%E9%97%B0%E5%B9%B4

step1: 年份除以400可整除=閏年

假設年份為2015年


『如果』 『年份』 『除以』 『400』 『餘數等於』 『0』 

『等於』『閏年』

變成程式的話就是:





如果((年份 對後數取餘數 400) 等於 0){ 

是不是閏年 = 是

}

變成程式的話就是:





if ((year    %%       400)  == 0){ 

lear_year = TRUE

}

step2:西元年份除以4可整除,但除以100可整除=不是閏年。

可以用or


if((year %% 4) == 0){ 

print("Leap year")
}
if((year %% 100) == 0){

print("NOT leap year")
}

咦?好像有地方怪怪的

除以4可整除,那除以100一定也可以整除啊

else()出現了


if ((year1 %% 4)==0){ 
if ((year1 %% 100)==0){
print("NOT leap year")
} else {
print("Leap year")
} }

step4:西元年份除以100可整除,但除以400不可整除=不是閏年。

聰明的各位應該發現到這邊有好幾個判斷出現了,

還記得前面講過有四個條件嗎?


if ((year1 %% 4)==0){
  if ((year1 %% 100)==0){
    if ((year1 %% 400)==0)
      print("Leap year")
    else
      print("Not leap year")
  } else {
    print("Leap year")
  }
} else {
  print("Not leap year")
}

遊戲時間

用R玩遊戲

  1. 猜數字的小遊戲

  2. 猜幾A幾B的遊戲

  3. 猜幾A幾B的遊戲:和電腦比賽 (還在寫)

  4. 圈叉遊戲

  5. 圈叉遊戲:只有平手或電腦必勝(還在寫)

  6. 河內塔

  7. 五子旗(還在寫)

  8. 撲克21點(還在寫)

迴圈

迴圈說明

某個動作重複做多少次,可減少重複寫code的時間

迴圈使用的時機

1. 重複有限次數 (for loop)

2. 重複次數不能確定 (while loop)

3. 重複無限次數 (while loop)

for 迴圈

1. 開始條件


2. 次數累計


3. 停止條件

for()

for (累進變數 in 開始條件:終止條件 )


for(x in 1:10) {
  print(x)
}

## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10

for(): ex2

for ( 累進變數 in 向量 )


c1 = c(1:10)
for(x in c1) {
  print(x)
}

## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10

while()

while (條件不成立的話,就停止)


while(判斷式) {}

如果判斷式不成立就停止,否則一直執行迴圈的程式

最簡單的無限迴圈





while(1){

    print("I love R")   

}

break:

當進入迴圈時,如果想離開迴圈的話,這時後可以用break跳出迴圈

會了for,可以怎麼用?

這是copy-paste沒錯

算有多少個閏年

請說明一段時間內,有多少年是閏年

提醒:可以用for來持續檢查某一年是否是閏年,例如:開始年:1000,結束年:2015



for(年 in 開始年:結束年){ 

判斷是否是閏年

如果是閏年則次數 + 1
}

先輸入條件



yearS = 1000 

# yearS = as.integer(readline("input start year:")) 

yearE = 2015 

# yearE = as.integer(readline("input end year:")) 

year_cnt = 0

用之前講的閏年練習


for (n in yearS:yearE){ 
    if ((year1 %% 4)==0){
        if ((year1 %% 100)==0){
            if ((year1 %% 400)==0)
                is_leap_year = TRUE
            else
                is_leap_year = FALSE
            } else {
                is_leap_year = TRUE
            }
        } else {
        is_leap_year = FALSE
    }   


    if (is_leap_year == TRUE)
    year_cnt = year_cnt + 1 
  }
}
paste("總共有:", year_cnt," 個閏年")

## [1] "總共有: 246  個閏年"

範例:閏年判斷程式:

把之前的閏年判斷包成函式:leap_year()


leap_year = function(year1){

    if ((year1 %% 4)==0){
      if ((year1 %% 100)==0){
        if ((year1 %% 400)==0)
          return TRUE   # 是閏年
        else
          return FALSE  # 不是閏年
      } else {
        return TRUE     # 是閏年
      }
    } else {
      return FALSE      # 不是閏年
    }
}

把 leap_year()放到for迴圈中


yearS = 1000 # 或是可以輸入:as.integer(readline("input start year:")) 來自己輸入開始年
yearE = 2015 # 或是可以輸入:as.integer(readline("input end year:")) 來輸入結束年
year_cnt=0


for (n in yearS:yearE){

  if (leap_year(n)){

    year_cnt = year_cnt+1

  }
}
paste("總共有:", year_cnt," 個閏年")

## [1] "總共有: 246  個閏年"

延伸題目:

除了多少年之外,還想知道想知道哪些年是閏年

Debug:除錯

為什麼要除錯:

每天都在問神奇海螺

E=MC^2

人都可能被劈腿,手一定有機會出鎚,

Debug 常用指令:





debug(fun) 

undebug(fun)

使用方法:


debug(now_time) 
now_time()
undebug(now_time)

測試:

用debug來測試前面好的閏年程式:leap_year()

Error / Exception Handling:錯誤/例外管理

Error/Exception Handling

輸入範例

data_in = list(1, 2, 4, -5, "I^love^R", 0, 10) 
for(input in data_in) {
print(log(input))
}

結果:Error


[1] "0"
[1] "0.693147180559945"
[1] "1.38629436111989"
[1] "NaN"


Error in log(input) : non-numeric argument 

to mathematical function

此外: Warning message:

In log(input) : 產生了 NaNs

Error Handling: 使用try()

try的用法:


data_in = list(1, 2, 4, -5, "I^love^R", 0, 10)

for(input in data_in) {

  try(print(log(input)))
}

## [1] 0
## [1] 0.6931472
## [1] 1.386294
## Warning in log(input): NaNs produced
## [1] NaN
## [1] -Inf
## [1] 2.302585

Error Handling: 使用tryCatch()

可分別處理Warning和Error的事件

先設定發生Error和Warning時的應對方法

func_error = function(e){
print("this is a ERROR!!!")
}

func_warning = function(w){
print("just a wraning")
}

Error Handling: 使用tryCatch()來顯示錯誤


for(input in data_in) {
  tryCatch(print(log(input)),
  warning = func_warning ,
  error = func_error) }
## [1] 0
## [1] 0.6931472
## [1] 1.386294
## [1] "just a wraning"
## [1] "this is a ERROR!!!"
## [1] -Inf
## [1] 2.302585

結果


[1] 0

[1] 0.6931472

[1] 1.386294


[1] "just a wraning"

[1] "this is a ERROR!!!"

[1] -Inf


[1] 2.302585

小問題:

可以把發生錯誤的原始內容印出來嗎?

當然可以,but

小天使複習班:

R常用指令1

R常用指令2

小提醒:data.frame()


num1 = c(2, 3, 5) 

str1 = c("aa", "bb", "cc")

logic1 = c(TRUE, FALSE, TRUE)

df1 = data.frame(num1, str1, logic1)

# df1表示把data.frame()括號內的資料結合成為data.frame型態
##   num1 str1 logic1
## 1    2   aa   TRUE
## 2    3   bb  FALSE
## 3    5   cc   TRUE

比較c() vs data.frame()


num1 = c(2, 3, 5) 

str1 = c("aa", "bb", "cc")

logic1 = c(TRUE, FALSE, TRUE)

df2 = c(num1, str1, logic1)

# df2表示為c()括號中向量資料的結合
## [1] "2"     "3"     "5"     "aa"    "bb"    "cc"    "TRUE"  "FALSE" "TRUE"

比較rbind() vs data.frame()


num1 = c(2, 3, 5) 

str1 = c("aa", "bb", "cc")

logic1 = c(TRUE, FALSE, TRUE)

df3 = rbind(num1, str1, logic1)
# df3表示為rbind()括號中資料的結合
##        [,1]   [,2]    [,3]  
## num1   "2"    "3"     "5"   
## str1   "aa"   "bb"    "cc"  
## logic1 "TRUE" "FALSE" "TRUE"

小提醒:讀取檔案、表格:

讀取R檔並執行

如果想讀取儲存在硬碟的R檔的話,可以用source指令:


source("iris.r")

讀取CSV

CSV:(Comma-separated values:逗號分隔數值)

表格名稱 = read.csv("讀取的檔案")


iris_csv = read.csv("iris.csv") 

View(iris_csv)

一般文字表格

表格名稱 = read.table("讀取的檔案")


iris_tab = read.table("iris.txt")

View(iris_tab)

其他檔案:如excel等

表格名稱 = read.xls("讀取的檔案")

注意:這個需要額外的套件來支援excel格式,請先執行:library(gdata)
注意2:gdata套件的read.xls只能讀excel檔案中第一頁sheet,


library(gdata)

iris_xls = read.xls("iris.xls")

View(iris_xls)

課程再預告

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

R 專題實習 , by wush

Q & A

END!